#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define LINE_SIZE 1024
#define ARGC_SIZE 32
#define DELIM " \t"
#define EXIT_CODE 44
int quit=0;
int lastcode=0;
extern char ** environ;
char commandline[LINE_SIZE];
char myenv[LINE_SIZE];
char* argv[ARGC_SIZE];
const char *getusername()
{
    return getenv("USER");
}

const char *gethostname()
{
    return getenv("HOSTNAME");
}

const char *getpwd()
{
    return getenv("PWD");
}



void interact(char* cline,int size)
{    
    printf(LEFT"%s@%s %s"RIGHT LABLE,getusername(),gethostname(),getpwd());
    char* s=fgets(cline,size,stdin);
    assert(s);
    (void)s;
    cline[strlen(cline)-1]='\0';
}

int splitstring(char cline[],char* _argv[])//输出型参数
{
    int i=0;
    _argv[i++]=strtok(cline,DELIM);
    while(_argv[i++]=strtok(NULL,DELIM));
    return i-1;//返回命令行参数的个数,最后NULL的时候也++了
}

void NormalExecaute(char* _argv[])
{
        pid_t id = fork();
        if(id <0)
        {
            //子进程创建失败
            perror("fork fail");
            return;//while继续获取命令行
        }
        else if (id ==0)
        {
            //子进程--已经有命令行参数argv--模拟bash,所以去PATH找命令,选vp,e可选
            //execvpe(_argv[0],_argv,environ);
            execvp(_argv[0],_argv);
            exit(EXIT_CODE);
        }
        else
        {
            //父进程--等待
            int status=0;
            pid_t rid =waitpid(id,&status,0);
            if(rid==id)
            {
                //等待成功
                lastcode=WEXITSTATUS(status);
            }
        }
}
int buildCommand(char* _argv[],int _argc)
{
        //for(int j=0;j<argc;j++)
        //    printf("[%d],argv:%s\n",j,argv[j]);
        //
        //cd
        if(strcmp(_argv[0],"cd")==0 && _argc==2)
        {
            chdir(_argv[1]);
            return 1;
        }

        //export
        if(_argc == 2 && strcmp(_argv[0],"export")==0)
        {
            strcpy(myenv,_argv[1]);
            putenv(myenv);
            return 1;
        }


        //echo
        if(_argc ==2 && strcmp(_argv[0],"echo")==0)
        {
            if(strcmp(_argv[1],"$?")==0)
            {
                printf("%d\n",lastcode);
                lastcode=0;
                return 1;
            }
            if(*_argv[1]=='$')
            {
                printf("%s\n",getenv(_argv[1]+1));
            }
            else
            {
                printf("%s\n",_argv[1]);
            }
            return 1;
        }


        return 0;// 返回1执行自建命令成功   0不是自建命令
}
int main()
{
    while(!quit)
    {
        //2.交互问题,获取命令行
        interact(commandline,sizeof(commandline));


        //3.分割命令行获得命令行参数
        int argc=splitstring(commandline,argv);
        if(argc==0) continue;


        //4.指令的判断
        int n =buildCommand(argv,argc);

        //5.普通命令的执行(子进程执行)
        if(!n) NormalExecaute(argv);
    }
    return 0;
}
